#pragma once
#include <memory>
#include "InetAddr.hpp"
#include "Socket.hpp"
#include "Connection.hpp"
#include "Reactor.hpp"
#include "HandlerConnection.hpp"
using namespace socket_ns;

class Listener
{
public:
    Listener(uint16_t port, HandlerConnection &hc)
        : _port(port), _listenSock(std::make_unique<TcpSocket>()), _hc(hc)
    {
        _listenSock->BuildListenSocket(InetAddr(port, "0"));
    }
    void AcceptClient(Connection *con)
    {
        while (true)
        {
            InetAddr clientAddr;
            int errcode;
            int newfd = _listenSock->Accepter(clientAddr, errcode);
            if(newfd >= 0)
            {

            con->_R->AddConnection(newfd, EPOLLIN | EPOLLET,
                                   std::bind(&HandlerConnection::Recv, &_hc, std::placeholders::_1),
                                   std::bind(&HandlerConnection::Send, &_hc, std::placeholders::_1),
                                   std::bind(&HandlerConnection::Except, &_hc, std::placeholders::_1));
            }
            else
            {
                if(errcode == EWOULDBLOCK || errcode == EAGAIN)
                {
                    LOG(INFO, "accept all link\n");
                    break;
                }
                else if(errcode == EINTR)
                {
                    LOG(INFO, "accept interupt by signal\n");
                    break;
                }
                else
                {
                    LOG(WARNING, "accept fail\n");
                    break;
                }

            }
        }
    }
    int Socket()
    {
        return _listenSock->Sockfd();
    }
    ~Listener()
    {
        _listenSock->Close();
    }

private:
    uint16_t _port;
    std::unique_ptr<socket_ns::Socket> _listenSock;
    HandlerConnection& _hc;
};